﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Apollo.Web;
using Apollo.Core;
using Apollo;

namespace Apollo.Website
{
    public partial class Controls_Edit_FormItemRelation : System.Web.UI.UserControl, IFormItem
    {
        public FormItem Item { get; set; }

        public object TargetObject { get; set; }

        protected void Page_Load(object sender, EventArgs e)
        {
            this.LabelPropertyName.CssClass = "property_name";
            
            if (!this.IsPostBack)
            {
                this.LabelPropertyName.Text = this.Item.Projection.DisplayName;

                Entity belongsTo = this.Item.Projection.EntityProperty.BelongToEntity;

                if (belongsTo == null)
                    return;

                object obj = null;

                if (this.TargetObject != null) // EXISTING
                    obj = this.Item.Projection.Apply(this.TargetObject);
                else if (!string.IsNullOrEmpty(this.Item.Projection.EntityProperty.DefaultValue) || !string.IsNullOrEmpty(this.Item.DefaultValue)) {
                    try
                    {
                        Projection prj = new Projection(
                            this.Item.Projection.EntityProperty.BelongToEntity.IdentifierProperty,
                            this.Item.Projection.EntityProperty.BelongToEntity.MappedClass);

                        if (string.IsNullOrEmpty(this.Item.DefaultValue))
                            obj = Apollo.Application.CurrentSession.Get(
                                this.Item.Projection.EntityProperty.BelongToEntity.MappedClass
                                , Apollo.Application.Deserialize(
                                    this.Item.Projection.EntityProperty.DefaultValue, prj.PropertyType));
                        else
                            obj = Apollo.Application.CurrentSession.Get(
                                this.Item.Projection.EntityProperty.BelongToEntity.MappedClass
                                , Apollo.Application.Deserialize(
                                    this.Item.DefaultValue, prj.PropertyType));
                    }
                    catch { }
                }

                string editUrl = string.IsNullOrEmpty(belongsTo.CustomEditUrl) ?
                                "/Edit.aspx?EntityId=" + belongsTo.Id.ToString() + "&ObjectId={ObjectId}" :
                                belongsTo.CustomEditUrl;

                if (obj != null)
                {
                    Projection idProjection = new Projection(belongsTo.IdentifierProperty, this.Item.Projection.PropertyType);
                    HiddenFieldID.Value = idProjection.Apply(obj).ToString();

                    if (belongsTo.IdentifierProperty != belongsTo.DisplayProperty)
                    {
                        Projection displayProjection = new Projection(belongsTo.DisplayProperty, this.Item.Projection.PropertyType);
                        object displayValue = displayProjection.Apply(obj);

                        if (displayValue != null)
                            HyperLinkValue.Text = displayValue.ToString();
                        else
                            HyperLinkValue.Text = "{" + HiddenFieldID.Value + "}";
                    }
                    else
                        HyperLinkValue.Text = HiddenFieldID.Value;

                    TextBoxValue.Text = HyperLinkValue.Text;
                    HiddenFieldDisplayName.Value = HyperLinkValue.Text;
                }
                else
                {
                    // check belong to
                    if (this.Item.Projection.ProjectionPath == this.Request["property"])
                    {

                        Projection belongsToIdProjection = new Projection(belongsTo.IdentifierProperty, belongsTo.MappedClass);
                        Projection belongsToDisplayProjection = new Projection(belongsTo.DisplayProperty, belongsTo.MappedClass);

                        object belongsToIdValue = Apollo.Application.Deserialize(this.Request["belongsTo"], belongsToIdProjection.PropertyType);

                        if (belongsToIdValue != null)
                        {
                            HiddenFieldID.Value = belongsToIdValue.ToString();

                            obj = Apollo.Application.CurrentSession.Get(belongsTo.MappedClass, belongsToIdValue);

                            object belongsToDisplayValue = belongsToDisplayProjection.Apply(obj);
                            HyperLinkValue.Text = belongsToDisplayValue.ToString();
                            TextBoxValue.Text = belongsToDisplayValue.ToString();
                            HiddenFieldDisplayName.Value = belongsToDisplayValue.ToString();
                        }
                    }
                }

                if (!string.IsNullOrEmpty(belongsTo.IconPath))
                    ImageButtonIcon.ImageUrl = belongsTo.IconPath;

                int viewId = belongsTo.DefaultView.Id;

                if (this.Item.Projection.EntityProperty != null && this.Item.Projection.EntityProperty.CustomView != null)
                    viewId = this.Item.Projection.EntityProperty.CustomView.Id;

                LiteralJS.Text = @"
<script type=""text/javascript"">
    var entityRelation" + this.ClientID + " = new apolloRelation('" + HyperLinkValue.ClientID + "','"
                + TextBoxValue.ClientID +"','" 
                + ImageButtonIcon.ClientID + "','" 
                + ImageButtonDelete.ClientID + "','" 
                + HiddenFieldID.ClientID + "','" 
                + HiddenFieldDisplayName.ClientID + "'," 
                + viewId.ToString() + ",'" + editUrl + @"');
</script>
            ";

                this.ImageButtonIcon.Visible = (this.Item.Type != FormItemType.ReadOnly);
                this.ImageButtonDelete.Visible = (this.Item.Type != FormItemType.ReadOnly);
                if (this.Item.Type == FormItemType.ReadOnly)
                {
                    TextBoxValue.CssClass = "property_relation_disabled";
                    HyperLinkValue.CssClass = "property_relation_disabled";
                }
            }
        }

        public ActionMessage Save(object obj)
        {
            if (this.Item.Type == FormItemType.ReadOnly)
                return null;

            try
            {
                // get the current value of the relation
                object objRelationProperty = this.Item.Projection.Apply(obj);
                if (objRelationProperty == null) // create it if necessary
                    objRelationProperty = Activator.CreateInstance(this.Item.Projection.PropertyType);

                // gets the projection for relation -> identifier
                Projection relationIdProjection = new Projection(
                      this.Item.Projection.EntityProperty.BelongToEntity.IdentifierProperty
                    , this.Item.Projection.PropertyType);

                // get the current value of the relation -> identifier
                object objRelationId = relationIdProjection.Apply(objRelationProperty);

                if (objRelationId.ToString() != this.HiddenFieldID.Value)
                {
                    if (this.Item.Type == FormItemType.Required && this.HiddenFieldID.Value == "")
                    {
                        LabelPropertyName.CssClass = "property_name_error";
                        return new ActionMessage(this.Item.Projection.DisplayName + " can not be null", ActionMessageType.Error);
                    }

                    if (this.HiddenFieldID.Value == "")
                        this.Item.Projection.SetValue(obj, null); // set it to null
                    else
                    {
                        // recreate it so Nhibernate will think that it's the same item
                        objRelationProperty = Activator.CreateInstance(this.Item.Projection.PropertyType);

                        // set it to new value
                        relationIdProjection.SetValue(objRelationProperty, Apollo.Application.Deserialize(this.HiddenFieldID.Value, relationIdProjection.PropertyType));

                        if (this.Item.Type == FormItemType.Required && objRelationProperty == null)
                        {
                            LabelPropertyName.CssClass = "property_name_error";
                            return new ActionMessage(this.Item.Projection.DisplayName + " can not be null", ActionMessageType.Error);
                        }

                        this.Item.Projection.SetValue(obj, objRelationProperty);
                    }
                }
            }
            catch (Exception ex)
            {
                return new ActionMessage(this.Item.Projection.DisplayName + " error: " + ex.Message, ActionMessageType.Error);
            }

            return null;
        }
    }
}